package com.xwaf.platform.system.auth.serviceimpl;

import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.plugins.Page;
import com.xwaf.platform.common.service.service.CrudService;
import com.xwaf.platform.common.utils.annotation.Compensable;
import com.xwaf.platform.system.api.entity.DataBase;
import com.xwaf.platform.system.api.entity.auth.Account;
import com.xwaf.platform.system.api.entity.auth.AccountFreeze;
import com.xwaf.platform.system.api.entity.pay.Order;
import com.xwaf.platform.system.api.service.auth.AccountService;
import com.xwaf.platform.system.auth.dao.AccountDao;
import com.xwaf.platform.system.auth.dao.AccountFreezeDao;

@Transactional(readOnly = true)
@Service("accountService")
public class AccountServiceImpl extends CrudService<AccountDao, Account> implements AccountService {
	private static final Logger log = LoggerFactory.getLogger(AccountServiceImpl.class);
	@Autowired
	private AccountDao accountDao;
	@Autowired
	private AccountFreezeDao accountFreezeDao;

	@Override
	public Page<Account> selPageList(Page<Account> page, Account account) {
		List<Account> list = accountDao.selPageList(page, account);
		page.setRecords(list);
		return page;
	}

	@Transactional(readOnly = false, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	@Compensable(confirmMethod = "decreaseAccountConfirm", cancelMethod = "decreaseAccountCancel")
	@Override
	public Integer decreaseAccount(Order order) {
		log.info("==================decrease开始=====================req:{}" + order);
		Account entity = new Account();
		entity.setUserId(order.getBuyerLogonId());
		Account dbAccount = accountDao.selectOne(entity);
		int result = 0;
		if (dbAccount != null) {
			result = accountDao.freezeAmount(dbAccount.getId(), order.getTotalFee(), new Date());
			if (result > 0) {
				// 模拟try阶段处理超时
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				AccountFreeze accountFreeze = new AccountFreeze();
				accountFreeze.setId(DataBase.getDataBaseId(DataBase.AF));
				accountFreeze.setOrderId(order.getId());
				accountFreeze.setFreezeAmount(order.getTotalFee());
				accountFreeze.setUserId(dbAccount.getId());
				accountFreeze.setCreateTime(new Date());
				result = accountFreezeDao.insert(accountFreeze);
			}
			// 模拟try阶段处理出现异常
			// throw new Exception("扣款出现异常");
		}
		log.info("==================decrease结束=====================req:{}" + order);
		return result;
	}

	/** 幂等性 */
	@Transactional(readOnly = false, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Integer decreaseAccountConfirm(Order order) {
		log.info("==================decreaseAccountConfirm开始=====================req:{}" + order);
		AccountFreeze entity = new AccountFreeze();
		entity.setUserId(order.getBuyerLogonId());
		AccountFreeze accountFreeze = accountFreezeDao.selectOne(entity);
		int result = 0;
		if (accountFreeze != null) {
			result = accountFreezeDao.deleteById(accountFreeze.getId());
			if (result > 0) {
				result = accountDao.freezeAmountConfirm(order.getBuyerLogonId(), order.getTotalFee(), new Date());
			}
		}
		// int result =
		// accountFreezeMapper.deleteFreezeRecord(req.getOrderId());
		// 参考 https://www.jianshu.com/p/11c46dbfd6e7
		// https://www.jianshu.com/p/f8495015dace
		log.info("==================decreaseAccountConfirm结束=====================req:{}" + order);
		return result;
	}

	/** 幂等性 */
	@Transactional(readOnly = false, isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
	public Integer decreaseAccountCancel(Order order) {
		log.info("==================decreaseAccountCancel开始=====================req:{}" + order);
		AccountFreeze entity = new AccountFreeze();
		entity.setUserId(order.getBuyerLogonId());
		AccountFreeze accountFreeze = accountFreezeDao.selectOne(entity);
		int result = 0;
		if (accountFreeze != null) {
			result = accountFreezeDao.deleteById(accountFreeze.getId());
			if (result > 0) {
				result = accountDao.freezeAmountCancel(order.getBuyerLogonId(), order.getTotalFee(), new Date());
			}
		}
		log.info("==================decreaseAccountCancel结束=====================req:{}" + order);
		return result;
	}
}
